package com.moli.iov.handle.alarm.service.impl;

import com.moli.iov.base.enums.AlarmAuthEnum;
import com.moli.iov.base.remote.ISysParamSettingsRemoteService;
import com.moli.iov.handle.alarm.biz.OfflineHandler;
import com.moli.iov.handle.alarm.biz.utils.AlarmUtils;
import com.moli.iov.handle.alarm.constants.AlarmMemoConstant;
import com.moli.iov.handle.alarm.enums.AlarmCodeEnum;
import com.moli.iov.handle.alarm.enums.AlarmSourceEnum;
import com.moli.iov.handle.alarm.enums.AlarmStatusEnum;
import com.moli.iov.handle.alarm.enums.AntiShakeEnum;
import com.moli.iov.handle.alarm.enums.CheckAlarmEnum;
import com.moli.iov.handle.alarm.model.dto.AlarmDto;
import com.moli.iov.handle.alarm.model.dto.AlarmInfoDto;
import com.moli.iov.handle.alarm.model.dto.AuthDto;
import com.moli.iov.handle.alarm.model.dto.DisarmAlarmDto;
import com.moli.iov.handle.alarm.model.dto.req.AlarmReqDto;
import com.moli.iov.handle.alarm.model.dto.req.DisarmFenceAlarmReqDto;
import com.moli.iov.handle.alarm.model.po.AlarmInfo;
import com.moli.iov.handle.alarm.model.po.extend.FenceInfoExtend;
import com.moli.iov.handle.alarm.service.IAlarmInfoRequestService;
import com.moli.iov.handle.alarm.service.IAlarmInfoService;
import com.moli.iov.handle.alarm.service.IAlarmInfoTaskRequestService;
import com.moli.iov.handle.alarm.service.IAlarmOtherService;
import com.moli.iov.real.model.res.VehicleLocationDto;
import com.moli.iov.real.service.IRealService;
import com.moli.iov.rest.RestResponse;
import com.moli.iov.util.CommonUtils;
import com.moli.iov.util.StringUtil;
import java.util.Arrays;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

/**
 * <p>
 * OP报警
 * </p>
 *
 * @author: zql
 * @Date: 2019/2/20 11:03
 */
@Slf4j
@Component("alarmInfoTaskRequestService")
public class AlarmInfoTaskRequestServiceImpl implements IAlarmInfoTaskRequestService {

  @Autowired
  private OfflineHandler offlineHandler;

  @Autowired
  private AlarmUtils alarmUtils;

  @Autowired
  private ISysParamSettingsRemoteService sysParamSettingsRemoteService;

  @Autowired
  private IAlarmInfoRequestService alarmInfoRequestService;

  @Autowired
  private IAlarmOtherService alarmOtherService;

  @Autowired
  private IAlarmInfoService alarmInfoService;

  @Autowired
  private ThreadPoolTaskExecutor taskExecutor;

  @Autowired
  private IRealService realService;

  /**
   * 离线报警时长
   */
  @Value("${OFF_LINE_TIME}")
  private long offLineTime;

  /**
   * 车辆离线（task 每隔5个小时调用一次）
   */
  @Override
  public void offLineAlarm() {

    offlineHandler.alarm();
  }

  /**
   *  添加里程异变报警
   * @param alarmReqDto
   * @return
   */
  @Override
  public RestResponse mileageExChangeAlarm(AlarmReqDto alarmReqDto) {

    log.info("添加里程异变报警 入参：{}", alarmReqDto);


    RestResponse restResponse = mileageExChangeAlarmValid(alarmReqDto);
    if(!restResponse.flag){
      return restResponse;
    }

    AuthDto authDto = alarmOtherService.isAuthorized(alarmReqDto.getVin());
    if(authDto.getAlarmAuths().contains(AlarmAuthEnum.MILE_EXCHANGE.getFlag())){
      log.error("添加里程异变报警 失败 tbox未授权 或 里程异变报警 不监控 vin:{}", alarmReqDto.getVin());
      return RestResponse.failure("tbox未授权");
    }

    try{
      alarmInfoRequestService.alarm(assemblyAlarmDto(alarmReqDto));
      return RestResponse.success();
    }catch (Exception e){
      log.error("添加里程异变报警 异常", e);
      return RestResponse.failure("添加里程异变报警失败");
    }

  }

  /**
   * 校验
   * @param alarmReqDto
   * @return
   */
  private RestResponse mileageExChangeAlarmValid(AlarmReqDto alarmReqDto){
    if(alarmReqDto == null || StringUtil.isBlank(alarmReqDto.getVin())){
      return RestResponse.failure("vin不能为空");
    }

    if(alarmReqDto.getCurrentMileage() == null){
      return RestResponse.failure("当前里程不能为空");
    }

    if(alarmReqDto.getDifferenceMileage() == null){
      return RestResponse.failure("异变里程数不能为空");
    }

    if(alarmReqDto.getMilExThreshold() == null){
      return RestResponse.failure("异变阈值不能为空");
    }

    if(alarmReqDto.getLastTimeMileage() == null){
      return RestResponse.failure("上次里程不能为空");
    }

    return RestResponse.success();
  }

  /**
   * 组装数据
   * @param alarmReqDto
   * @return
   */
  private AlarmDto assemblyAlarmDto(AlarmReqDto alarmReqDto){
    AlarmDto alarmDto = new AlarmDto();
    CommonUtils.copyProperties(alarmReqDto, alarmDto);

    String memo = AlarmMemoConstant.MILE_EX_CHANGE_MEMO
        .replaceAll("@1", String.valueOf(alarmReqDto.getLastTimeMileage()));
    memo = memo.replaceAll("@2", String.valueOf(alarmReqDto.getCurrentMileage()));

    alarmDto.setAlarmCode(AlarmCodeEnum.MILEAGE_EXCEPTION_CHANGE.getFlag());
    alarmDto.setAlarmLevel(AlarmCodeEnum.MILEAGE_EXCEPTION_CHANGE.getLevel());
    alarmDto.setAlarmType(AlarmSourceEnum.PLATFORM.getFlag());
    alarmDto.setIsAntiShake(AntiShakeEnum.NO.getFlag());
    alarmDto.setMemo(memo);
    alarmDto.setIsCheckAlarming(CheckAlarmEnum.NO.isFlag());
    alarmDto.setCollectDate(alarmReqDto.getCollectDate());
    alarmDto.setActualMileage(alarmReqDto.getActualMileage());
    alarmDto.setGpsMileage(alarmReqDto.getGpsMileage());

    return alarmDto;
  }

  /**
   * 解除围栏报警
   * @param disarmFenceAlarmReqDto
   * @return
   */
  @Override
  public RestResponse disarmFenceAlarm(DisarmFenceAlarmReqDto disarmFenceAlarmReqDto) {
    log.info("围栏解绑 解除围栏报警 入参：{}", disarmFenceAlarmReqDto);
    if(disarmFenceAlarmReqDto == null || StringUtil.isBlank(disarmFenceAlarmReqDto.getVin())){
      return RestResponse.failure("vin不能为空");
    }

    if(disarmFenceAlarmReqDto.getFenceId() == null){
      return RestResponse.failure("围栏不能为空");
    }


    //获取当前车辆经纬度
    String vin = disarmFenceAlarmReqDto.getVin();
    Long fenceId = disarmFenceAlarmReqDto.getFenceId();
    double lon = 0.0;
    double lat = 0.0;

    try {
      RestResponse<VehicleLocationDto> location = realService.getLocation(vin);
      if(location != null && location.flag && location.getData() != null){
        VehicleLocationDto vehicleLocationDto = location.getData();
        lon = vehicleLocationDto.getLongitude();
        lat = vehicleLocationDto.getLatitude();
      }
    } catch (Exception e) {
      log.error("获取当前车辆经纬度 异常", e);
    }



    subDisarmFenceAlarm(vin, AlarmCodeEnum.OUT_FENCE.getFlag(), fenceId, lon, lat);

    subDisarmFenceAlarm(vin, AlarmCodeEnum.IN_FENCE.getFlag(), fenceId, lon, lat);

    return RestResponse.success();
  }

  /**
   * 解除围栏报警
   * @param vin
   * @param alarmCode
   * @param fenceId
   * @param lon
   * @param lat
   */
  private void subDisarmFenceAlarm(String vin, int alarmCode,
      Long fenceId, double lon, double lat){
    try{
      taskExecutor.execute(()->{

        AlarmInfoDto alarmInfoDto = new AlarmInfoDto();
        alarmInfoDto.setVin(vin);
        alarmInfoDto.setAlarmCode(alarmCode);
        alarmInfoDto.setStatues(Arrays.asList(AlarmStatusEnum.ALARMING.getFlag(), AlarmStatusEnum.IGNORE.getFlag()));
        List<AlarmInfo> alarmInfos = alarmInfoService.listAlarmInfo(alarmInfoDto);

        for(AlarmInfo alarmInfo : alarmInfos){

          FenceInfoExtend fenceInfoExtend = alarmInfo.getFenceInfo();
          if(fenceInfoExtend == null || !fenceInfoExtend.getFenceId().equals(fenceId)){
            continue;
          }

          DisarmAlarmDto disarmAlarmDto = new DisarmAlarmDto(vin,
              alarmCode, AntiShakeEnum.NO.getFlag(), lon, lat);
          alarmInfoRequestService.disarmAlarm(disarmAlarmDto);

          alarmUtils.initAlarmOnTimes(vin, alarmCode);
        }
      });
    }catch (Exception e){
      log.error("解除围栏报警 异常", e);
    }
  }


}
